//
//  File.swift
//  
//
//  Created by youzy01 on 2020/9/25.
//

import Foundation
import UIKit

public struct Accessory {
    public static var defaultEmptyView: (() -> DataEmptyable) = {
        return EmptyView()
    }

    public static var defaultErrorView: (() -> ViewErrorable) = {
        return ErrorView()
    }

    public static var defaultLoadingView: (() -> LoadAnimateable) = {
        return LoadingView()
    }

    public static var defaultHudLoadingView: (() -> LoadAnimateable) = {
        return LoadingView()
    }
}

public struct EG<Base> {
    let view: Base

    public init(view: Base) {
        self.view = view
    }
}

protocol Accessorialable {
    var emptyView: DataEmptyable? { get }
    var errorView: ViewErrorable? { get }
    var loadingView: LoadAnimateable? { get }
    var loadingHud: HUD? { get }

    func update(_ errorView: ViewErrorable)
    func update(_ emptyView: DataEmptyable)
    func update(_ loadingView: LoadAnimateable)
    func update(_ loadingHud: HUD)
}

extension EG: Accessorialable where Base: UIView {
    var emptyView: DataEmptyable? {
        if view.emptyView == nil {
            update(Accessory.defaultEmptyView())
        }
        return view.emptyView
    }

    var errorView: ViewErrorable? {
        if view.errorView == nil {
            update(Accessory.defaultErrorView())
        }
        return view.errorView
    }

    var loadingView: LoadAnimateable? {
        if view.loadingView == nil {
            update(Accessory.defaultLoadingView())
        }
        return view.loadingView
    }

    var loadingHud: HUD? {
        if view.loadingHud == nil {
            update(HUD.loading(to: view))
        }
        return view.loadingHud
    }

    /// 更新错误提示view
    /// - Parameter errorView: 错误提示view
    public func update(_ errorView: ViewErrorable) {
        errorView.frame = view.bounds
        errorView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.errorView = errorView
    }

    /// 更新无数据提示view
    /// - Parameter emptyView: 无数据提示view
    public func update(_ emptyView: DataEmptyable) {
        emptyView.frame = view.bounds
        emptyView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.emptyView = emptyView
    }

    /// 更新全屏加载动画视图
    /// - Parameter loadingView: 全屏加载动画
    public func update(_ loadingView: LoadAnimateable) {
        loadingView.frame = view.bounds
        loadingView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.loadingView = loadingView
    }

    /// 更新加载动画Hud
    /// - Parameter loadingHud: 加载动画Hud
    func update(_ loadingHud: HUD) {
        view.loadingHud = loadingHud
    }

    public func update(emptyTitle: String) {
        emptyView?.update(title: emptyTitle)
    }

    public func update(emptyContent: String) {
        emptyView?.update(content: emptyContent)
    }

    public func update(emptyImage: UIImage?) {
        emptyView?.update(image: emptyImage)
    }

    public func showError(_ error: NTError, atView: UIView? = nil, observer: ErrorHandlerObserverType? = nil) {
        guard let errorView = errorView else { return }
        if let view = atView {
            errorView.frame = view.frame
        }
        view.addSubview(errorView)
        errorView.update(error, observer: observer)
    }

    public func showLoading() {
        guard let loadingView = loadingView else { return }
        print("显示全屏刷新动画", loadingView)
        loadingView.frame = view.bounds
        loadingView.start()
        view.addSubview(loadingView)
        loadingView.bringSubviewToFront(view)
    }

    public func hideLoading() {
        print("隐藏全屏刷新动画")
        loadingView?.removeFromSuperview()
    }

    public func showHud() {
        loadingHud?.show()
    }

    public func hideHud() {
        loadingHud?.hide()
    }

    public func showEmpty(at rect: CGRect? = nil) {
        guard let emptyView = emptyView else { return }
        if let rect = rect {
            emptyView.frame = rect
        } else {
            emptyView.frame = view.bounds
        }
        view.addSubview(emptyView)
    }

    public func hideEmpty() {
        emptyView?.removeFromSuperview()
    }
}
